package com.fc.advbox.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.fc.advbox.dao.*;
import com.fc.advbox.entity.UserTokenAcctEntity;
import com.fc.advbox.entity.UserTokenAcctTxnEntity;
import com.fc.advbox.entity.UserTokenAcctUnlockTxnEntity;
import com.fc.advbox.entity.UserTokenExtractRecordEntity;
import com.fc.advbox.service.IUserTokenAcctService;
import com.fc.advbox.utils.Constant;
import com.fc.advbox.utils.RRException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * Created by E7450 on 2018/7/27.
 */
@Service("userTokenAcctService")
public class UserTokenAcctServiceImpl extends BaseServiceImpl<UserTokenAcctEntity> implements IUserTokenAcctService {

    @Autowired
    private UserTokenAcctDao userTokenAcctDao;

    @Autowired
    private UserTokenAcctTxnDao userTokenAcctTxnDao;

    @Autowired
    private UserTokenExtractRecordDao userTokenExtractRecordDao;

    @Autowired
    private UserTokenAcctUnlockTxnDao userTokenAcctUnlockTxnDao;

    @Override
    public BaseDao getDao() {
        return userTokenAcctDao;
    }

    @Override
    public UserTokenAcctEntity changeTo(JSONObject params) {
        Long acctId = params.getLong("acctId");
        String changeType = params.getString("changeType");
        BigDecimal changeAmount = params.getBigDecimal("changeAmount");

        UserTokenAcctEntity userTokenAcct = userTokenAcctDao.queryObject(acctId);
        if(userTokenAcct == null)
        {
            throw new RRException("未找到该账户信息！");
        }

        String tnxComment = null;
        // changeType: 转换类型 toAble( 解锁中 ---> 可用 ) / toDeblocking(锁定 ---> 解锁中) / toLock(可用 ---> 锁定)
        if(Constant.TokenChangeType.TO_ABLE.getValue().equalsIgnoreCase(changeType))
        {
            //toAble( 解锁中 ---> 可用 )
            if(userTokenAcct.getDeblockingAmount() == null || userTokenAcct.getDeblockingAmount().compareTo(changeAmount) < 0)
            {
                throw new RRException("解锁中的数量不足, 请重新输入数量!");
            }
            userTokenAcct.setDeblockingAmount(userTokenAcct.getDeblockingAmount().subtract(changeAmount));
            userTokenAcct.setAbleAmount(userTokenAcct.getAbleAmount().add(changeAmount));
            tnxComment = "解锁中 --> 可用";
        }
        else if (Constant.TokenChangeType.TO_DEBLOCKING.getValue().equalsIgnoreCase(changeType))
        {
            //toDeblocking(锁定 ---> 解锁中)
            if(userTokenAcct.getLockAmount() == null || userTokenAcct.getLockAmount().compareTo(changeAmount) < 0)
            {
                throw new RRException("锁定的数量不足, 请重新输入数量!");
            }
            userTokenAcct.setLockAmount(userTokenAcct.getLockAmount().subtract(changeAmount));
            userTokenAcct.setDeblockingAmount(userTokenAcct.getDeblockingAmount().add(changeAmount));
            tnxComment = "锁定 --> 解锁中";

            // 解锁操作中， 保存用户解锁临时交易表
            saveTokenUnlockingTxnRecord(userTokenAcct.getId(), changeAmount, "解锁");
        }
        else if (Constant.TokenChangeType.TO_LOCK.getValue().equalsIgnoreCase(changeType))
        {
            // toLock(可用 ---> 锁定)
            if(userTokenAcct.getAbleAmount() == null || userTokenAcct.getAbleAmount().compareTo(changeAmount) < 0)
            {
                throw new RRException("锁定的数量不足, 请重新输入数量!");
            }
            userTokenAcct.setAbleAmount(userTokenAcct.getAbleAmount().subtract(changeAmount));
            userTokenAcct.setLockAmount(userTokenAcct.getLockAmount().add(changeAmount));
            tnxComment = "可用 --> 锁定";
        }
//        else if (Constant.TokenChangeType.DEBLOCKING_TO_LOCK.getValue().equalsIgnoreCase(changeType))
//        {
//            // deblockingToLock(解锁中 --> 锁定)
//            if(userTokenAcct.getDeblockingAmount() == null || userTokenAcct.getDeblockingAmount().compareTo(changeAmount) < 0)
//            {
//                throw new RRException("锁定中的数量不足, 请重新输入数量!");
//            }
//            userTokenAcct.setDeblockingAmount(userTokenAcct.getAbleAmount().subtract(changeAmount));
//            userTokenAcct.setLockAmount(userTokenAcct.getLockAmount().add(changeAmount));
//            tnxComment = "解锁中 --> 锁定";
//        }
        userTokenAcct.setUpdateTime(new Date());
        userTokenAcctDao.update(userTokenAcct);

        // 账号状态变化表
        saveAccountTxnRecord(acctId, userTokenAcct.getAccountType(), changeType, changeAmount, tnxComment);

        return userTokenAcct;
    }

    @Override
    public UserTokenAcctEntity extract(UserTokenExtractRecordEntity extractEntity) {

        UserTokenAcctEntity userTokenAcct = userTokenAcctDao.queryObject(extractEntity.getTokenAccountId());
        if(userTokenAcct == null)
        {
            throw new RRException("未找到该账户信息！");
        }

        if(userTokenAcct.getAbleAmount() == null || userTokenAcct.getAbleAmount().compareTo(extractEntity.getAmount()) < 0)
        {
            throw new RRException("申请数量超过账号可用数量, 请重新输入提现数量!");
        }
        // 更新账号信息
        userTokenAcct.setAbleAmount(userTokenAcct.getAbleAmount().subtract(extractEntity.getAmount()));
        userTokenAcct.setTotalAmount(userTokenAcct.getTotalAmount().subtract(extractEntity.getAmount()));
        userTokenAcct.setUpdateTime(new Date());
        userTokenAcctDao.update(userTokenAcct);


        // 提现交易记录表
        extractEntity.setServiceCharge(Constant.DEFAULT_TOKEN_EXTRACT_SERVICE_CHARGE_NUMBER);
        extractEntity.setActualAmount(extractEntity.getAmount().subtract(extractEntity.getServiceCharge()));// 实际到账数量
        extractEntity.setCreateTime(new Date());
        extractEntity.setStatus(Constant.Status.ENABLE.getValue()); //TODO
        extractEntity.setTxnId(UUID.randomUUID().toString()); // TODO
        userTokenExtractRecordDao.save(extractEntity);

        // 更新账号变化记录表
        saveAccountTxnRecord(userTokenAcct.getId(), userTokenAcct.getAccountType(), null, extractEntity.getAmount(), "提现");

        return userTokenAcct;
    }

    @Override
    public void cancelUnlockingTxn(Long unlockTxnId) {
        UserTokenAcctUnlockTxnEntity unlockTxnEntity = userTokenAcctUnlockTxnDao.queryObject(unlockTxnId);
        if(unlockTxnEntity == null)
        {
            throw new RRException("未找到解锁中交易记录对象！");
        }

        // 获取虚拟币账号信息
        UserTokenAcctEntity tokenAcctEntity = userTokenAcctDao.queryObject(unlockTxnEntity.getAcctId());
        if(tokenAcctEntity == null)
        {
            throw new RRException("未找到该用户账号！");
        }

        // 修改虚拟币账号总信息
        if(tokenAcctEntity.getDeblockingAmount() == null || tokenAcctEntity.getDeblockingAmount().compareTo(unlockTxnEntity.getAmount()) < 0)
        {
            throw new RRException("锁定中的数量不足, 请重新输入数量!");
        }
        tokenAcctEntity.setDeblockingAmount(tokenAcctEntity.getDeblockingAmount().subtract(unlockTxnEntity.getAmount()));
        tokenAcctEntity.setLockAmount(tokenAcctEntity.getLockAmount().add(unlockTxnEntity.getAmount()));
        tokenAcctEntity.setUpdateTime(new Date());
        userTokenAcctDao.update(tokenAcctEntity);

        // 删除解锁中交易记录表
        unlockTxnEntity.setStatus(Constant.Status.DISABLE.getValue());
        userTokenAcctUnlockTxnDao.update(unlockTxnEntity);

        // 更新账号变化记录表
        saveAccountTxnRecord(tokenAcctEntity.getId(), tokenAcctEntity.getAccountType(),
                "deblockingToLock", unlockTxnEntity.getAmount(), "取消解锁");

    }

    @Override
    public List<UserTokenAcctUnlockTxnEntity> queryUnlockTxnList(JSONObject params)
    {
        return userTokenAcctUnlockTxnDao.queryList(params);
    }

    /**
     * 保存交易记录
     * @param acctId
     * @param acctType
     * @param changeAmount
     * @param tnxComment
     */
    private void saveAccountTxnRecord(Long acctId, String acctType, String changeType, BigDecimal changeAmount, String tnxComment)
    {
        UserTokenAcctTxnEntity acctTxnEntity = new UserTokenAcctTxnEntity();
        acctTxnEntity.setAcctId(acctId);
        acctTxnEntity.setTxnType(acctType);
        acctTxnEntity.setChangeType(changeType);
        acctTxnEntity.setAmount(changeAmount);
        acctTxnEntity.setComments(tnxComment);
        acctTxnEntity.setCreateTime(new Date());
        acctTxnEntity.setTxnTime(new Date());
        userTokenAcctTxnDao.save(acctTxnEntity);
    }

    /**
     * 保存用户解锁临时交易表
     * @param acctId
     * @param amount
     * @param comment
     */
    private void saveTokenUnlockingTxnRecord(Long acctId, BigDecimal amount, String comment)
    {
        UserTokenAcctUnlockTxnEntity acctUnlockTxnEntity = new UserTokenAcctUnlockTxnEntity();
        acctUnlockTxnEntity.setAcctId(acctId);
        acctUnlockTxnEntity.setAmount(amount);
        acctUnlockTxnEntity.setComments(comment);
        acctUnlockTxnEntity.setStatus(Constant.Status.ENABLE.getValue());
        acctUnlockTxnEntity.setTxnTime(new Date());
        acctUnlockTxnEntity.setCreateTime(new Date());
        userTokenAcctUnlockTxnDao.save(acctUnlockTxnEntity);
    }
}
